//! 消息协议模块
//! 定义与 C# SignalR 兼容的消息格式

use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;

/// 消息类型枚举
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum MessageType {
    /// 调用方法
    Invocation,
    /// 流式调用
    StreamInvocation,
    /// 取消流式调用
    CancelInvocation,
    /// 流式数据项
    StreamItem,
    /// 完成
    Completion,
    /// 保持连接
    Ping,
    /// 关闭连接
    Close,
}

/// Hub 消息 - 对应 C# SignalR 的 HubMessage
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HubMessage {
    /// 消息类型
    #[serde(rename = "type")]
    pub message_type: MessageType,
    
    /// 目标方法名
    pub target: Option<String>,
    
    /// 参数列表
    pub arguments: Option<Vec<Value>>,
    
    /// 调用标识符
    pub invocation_id: Option<String>,
    
    /// 流式标识符
    pub stream_ids: Option<Vec<String>>,
    
    /// 错误信息
    pub error: Option<String>,
    
    /// 结果
    pub result: Option<Value>,
    
    /// 允许传输头
    pub allow_reconnect: Option<bool>,
    
    /// 自定义头
    pub headers: Option<HashMap<String, String>>,
}

impl HubMessage {
    /// 创建方法调用消息
    pub fn invocation(target: String, arguments: Vec<Value>) -> Self {
        Self {
            message_type: MessageType::Invocation,
            target: Some(target),
            arguments: Some(arguments),
            invocation_id: None,
            stream_ids: None,
            error: None,
            result: None,
            allow_reconnect: None,
            headers: None,
        }
    }
    
    /// 创建完成消息
    pub fn completion(invocation_id: String, result: Option<Value>, error: Option<String>) -> Self {
        Self {
            message_type: MessageType::Completion,
            target: None,
            arguments: None,
            invocation_id: Some(invocation_id),
            stream_ids: None,
            error,
            result,
            allow_reconnect: None,
            headers: None,
        }
    }
    
    /// 创建 Ping 消息
    pub fn ping() -> Self {
        Self {
            message_type: MessageType::Ping,
            target: None,
            arguments: None,
            invocation_id: None,
            stream_ids: None,
            error: None,
            result: None,
            allow_reconnect: None,
            headers: None,
        }
    }
}

/// Hub 响应消息
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HubResponse {
    /// 消息类型
    #[serde(rename = "type")]
    pub message_type: MessageType,
    
    /// 调用标识符
    pub invocation_id: Option<String>,
    
    /// 结果
    pub result: Option<Value>,
    
    /// 错误信息
    pub error: Option<String>,
    
    /// 是否允许重连
    pub allow_reconnect: Option<bool>,
}

impl HubResponse {
    /// 创建成功响应
    pub fn success(invocation_id: Option<String>, result: Value) -> Self {
        Self {
            message_type: MessageType::Completion,
            invocation_id,
            result: Some(result),
            error: None,
            allow_reconnect: None,
        }
    }
    
    /// 创建错误响应
    pub fn error(invocation_id: Option<String>, error: String) -> Self {
        Self {
            message_type: MessageType::Completion,
            invocation_id,
            result: None,
            error: Some(error),
            allow_reconnect: None,
        }
    }
    
    /// 创建流式数据项响应
    pub fn stream_item(invocation_id: String, item: Value) -> Self {
        Self {
            message_type: MessageType::StreamItem,
            invocation_id: Some(invocation_id),
            result: Some(item),
            error: None,
            allow_reconnect: None,
        }
    }
}

/// 内核请求类型 - 对应 C# 的 KernelRequestType
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct KernelRequest {
    pub flag: String,
    pub module: String,
    pub action: String,
    pub user_id: u64,
    pub target_id: u64,
    pub belong_id: u64,
}

/// 带参数的内核请求
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct KernelRequestWithArgs<T> {
    #[serde(flatten)]
    pub request: KernelRequest,
    
    #[serde(rename = "params")]
    pub args: T,
}

/// 数据源加载选项 - 对应 C# 的 DataSourceLoadOptions
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DataSourceLoadOptions {
    pub user_data: Vec<String>,
    pub options: Option<Value>,
    pub coll_name: String,
    pub form_id: Option<String>,
}

/// 集合更新数据 - 对应 C# 的 CollectUpdateData
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CollectUpdateData {
    pub r#match: Value,
    pub update: Value,
    pub options: Option<Value>,
}

/// 集合设置字段 - 对应 C# 的 CollectSetFields
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CollectSetFields {
    pub id: Option<String>,
    pub ids: Vec<String>,
    pub update: Value,
    pub options: Option<Value>,
}

/// 对象设置数据 - 对应 C# 的 ObjectSetData
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ObjectSetData {
    pub operation: String,
    pub data: Value,
}

/// 文件项数据 - 对应 C# 的 BucketItemData
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BucketItemData {
    pub target_id: u64,
    pub operation: String,
    pub data: Value,
}

/// 消息序列化和反序列化工具
pub struct MessageSerializer;

impl MessageSerializer {
    /// 序列化消息为 JSON
    pub fn serialize<T: Serialize>(message: &T) -> anyhow::Result<String> {
        serde_json::to_string(message).map_err(|e| anyhow::anyhow!("序列化失败: {}", e))
    }
    
    /// 反序列化 JSON 为消息
    pub fn deserialize<T: for<'a> Deserialize<'a>>(data: &str) -> anyhow::Result<T> {
        serde_json::from_str(data).map_err(|e| anyhow::anyhow!("反序列化失败: {}", e))
    }
    
    /// 解析 Hub 消息
    pub fn parse_hub_message(data: &str) -> anyhow::Result<HubMessage> {
        Self::deserialize(data)
    }
    
    /// 序列化 Hub 响应
    pub fn serialize_response(response: &HubResponse) -> anyhow::Result<String> {
        Self::serialize(response)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_message_serialization() {
        let message = HubMessage::invocation(
            "ThingLoad".to_string(),
            vec![serde_json::json!({ "belongId": "123" })],
        );
        
        let serialized = MessageSerializer::serialize(&message).unwrap();
        let deserialized: HubMessage = MessageSerializer::deserialize(&serialized).unwrap();
        
        assert_eq!(deserialized.target, Some("ThingLoad".to_string()));
    }
}